#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <fcntl.h>      

// 服务器端口号 
#define PORT 8080

int blink_interval = 0;       
int stop_blinking = 0;     
pthread_t blink_thread;  //用于存储LED闪烁线程的线程ID。

//根据输入的state（0或1）设置LED的状态，并输出相应的消息
void set_led(int state) {
    if (state) {
       int fd,ret;
    fd = open("/dev/leds", O_RDWR|O_NOCTTY|O_NDELAY);
    if(fd > 0)
    {
        ret = ioctl(fd, 1, 0);
    }
    close(fd);
	printf("LED IS ON\n");

    } else {
       int fd,ret;
    fd = open("/dev/leds", O_RDWR|O_NOCTTY|O_NDELAY);
    if(fd > 0)
    {
        ret = ioctl(fd, 0, 0);
    }
    close(fd);
	printf("LED IS OFF\n");

    }
}

//根据给定的间隔和次数来闪烁LED
void initial_blink(int interval, int times) {
    int i;
    for (i = 0; i < times; i++) {
        set_led(0);
        sleep(interval);
        set_led(1);
        sleep(interval);
    }
	printf("OK\n");
}

void* blink_led(void* arg) {		    
     while (!stop_blinking) {
        set_led(0);
        sleep(blink_interval);
        set_led(1);
        sleep(blink_interval);
    }
    return NULL;
}

//这个函数从客户端读取数据，并根据接收到的命令执行相应的操作。
void handle_client(int client_socket) {	
    char buffer[10240];
    int valread;
    while (1) {
        valread = read(client_socket, buffer, 1024);	          
	  if (valread > 0) {
            buffer[valread] = '\0';
            //设置`stop_blinking`为1， 打开状态。
            if (strcmp(buffer, "on") == 0) {
                stop_blinking = 1;
          
                set_led(1);
                       
            } 
              //停止任何当前的闪烁， 关闭状态。  
              else if (strcmp(buffer, "off") == 0) {
                stop_blinking = 1;
              
                set_led(0);
               
            } 
               //如果接收到以"blink"开头的命令，它会解析后面的数字作为闪烁间隔，并启动一个新的线程来闪烁LED。
              else if (strncmp(buffer, "blink", 5) == 0) {
                int interval = atoi(buffer + 6);	
                if (interval > 0) {
                    stop_blinking = 1;
             
                    blink_interval = interval;
                    stop_blinking = 0;
                    pthread_create(&blink_thread, NULL, blink_led, NULL);
                } 
                  //如果解析的间隔不是正数，它将输出一个错误消息。
                  else {
                    printf("Invalid interval received: %s\n", buffer);
                }
            } 
              //对于其他命令，它将输出一个错误消息表示接收到无效的命令。
              else {
                printf("Invalid command received: %s\n", buffer);
            }
        } else {
            break;
        }
    }
    close(client_socket);
}

int main() {		
    int server_fd, client_socket;		
    struct sockaddr_in address;		
    int opt = 1;
    int addrlen = sizeof(address);
    // 开机时 LED 闪烁
    initial_blink(1, 3);  // 每秒闪烁一次，闪烁3次

    // 创建一个IPv4、TCP协议的socket
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);		
    }

    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
        perror("Setsockopt failed");		
        close(server_fd);
        exit(EXIT_FAILURE); 
    }

    // 设置IPv4地址和端口
    address.sin_family = AF_INET;		
    address.sin_addr.s_addr = INADDR_ANY;	
    address.sin_port = htons(PORT);
    //使用 bind() 函数将套接字 server_fd 绑定到之前配置的地址和端口。
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("Bind failed");		

        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    // 开始监听连接请求
    if (listen(server_fd, 3) < 0) {		
        perror("Listen failed");		
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 循环接受客户端连接
    while (1) {		
		
        if ((client_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
            perror("Accept failed");
            close(server_fd);
            exit(EXIT_FAILURE);
        }
      
        handle_client(client_socket);
          }

    return 0;
}
